package com.example.armmvvm.ui.fallview

import android.os.Looper
import android.view.View
import io.reactivex.Observable
import io.reactivex.Observer
import io.reactivex.android.MainThreadDisposable
import io.reactivex.disposables.Disposables
import io.reactivex.internal.functions.Functions.EMPTY_RUNNABLE

/**
 *  author : yanghaozhang
 *  date : 2022/10/17 11:44
 *  description :
 */
fun View.postObservable(delayTime: Long = -1, runnable: Runnable): ViewPostObservable {
    val time = if (delayTime > 0) delayTime else -1
    return ViewPostObservable(this, runnable, time)
}

class ViewPostObservable(private val view: View, private val runnable: Runnable, private val delayTime: Long) : Observable<Unit>() {

    override fun subscribeActual(observer: Observer<in Unit>) {
        if (!checkMainThread(observer)) {
            return
        }
        val listener = PostDisposable(view, runnable, delayTime, observer)
        observer.onSubscribe(listener)
    }

    private fun checkMainThread(observer: Observer<*>): Boolean {
        if (Looper.myLooper() != Looper.getMainLooper()) {
            observer.onSubscribe(Disposables.fromRunnable(EMPTY_RUNNABLE))
            observer.onError(
                IllegalStateException(
                    "Expected to be called on the main thread but was " + Thread.currentThread().name
                )
            )
            return false
        }
        return true
    }

    private class PostDisposable(
        private val view: View,
        private val runnable: Runnable,
        private val delayTime: Long,
        private val observer: Observer<in Unit>
    ) : MainThreadDisposable() {

        init {
            if (delayTime == -1L) {
                view.post {
                    if (!isDisposed) {
                        runnable.run()
                        observer.onNext(Unit)
                        observer.onComplete()
                    }
                }
            } else {
                view.postDelayed({
                    if (!isDisposed) {
                        runnable.run()
                        observer.onNext(Unit)
                        observer.onComplete()
                    }
                }, delayTime)
            }

        }

        override fun onDispose() {
            view.removeCallbacks(runnable)
        }

    }
}